package com.dollar.juc.current_limit.semphore;


import java.util.List;
import java.util.Vector;
import java.util.concurrent.Semaphore;
import java.util.function.Function;

/**
 * 信号量实现限流，什么时候发放许可不由自己控制，这取决于任务的执行时长。
 * 也就是说不能做到时间维度的精确控制。
 * 这得求助于 令牌桶算法。
 *
 * @param <T>
 * @param <R>
 */
class ObjPool<T, R> {
    final List<T> pool;
    // 用信号量实现限流器
    final Semaphore sem;

    // 构造函数
    ObjPool(int size, T t) {
        pool = new Vector<T>() {
        };
        for (int i = 0; i < size; i++) {
            pool.add(t);
        }
        sem = new Semaphore(size);
    }

    // 利用对象池的对象，调用func
    R exec(Function<T, R> func) throws InterruptedException {
        T t = null;
        //原子操作
        sem.acquire();
        try {
            //t是原料，func 操作执行所需的原料
            t = pool.remove(0);
            return func.apply(t);
        } finally {
            //使用好原料资源，归还资源并归还许可
            pool.add(t);
            sem.release();
        }
    }
}
